package com.mdd.admin.service.course.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.query.MPJQueryWrapper;
import com.mdd.admin.LikeAdminThreadLocal;
import com.mdd.admin.service.course.ICourseService;
import com.mdd.admin.validate.common.PageParam;
import com.mdd.admin.validate.course.CourseColumnParam;
import com.mdd.admin.validate.course.CourseParam;
import com.mdd.admin.vo.course.*;
import com.mdd.common.core.PageResult;
import com.mdd.common.entity.course.*;
import com.mdd.common.entity.teacher.Teacher;
import com.mdd.common.mapper.course.*;
import com.mdd.common.mapper.teacher.TeacherMapper;
import com.mdd.common.utils.*;
import com.mdd.common.config.GlobalConfig;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * 课程实现类
 */
@Service
public class CourseServiceImpl implements ICourseService {
        
    @Resource
    CourseMapper courseMapper;

    @Resource
    CourseImageMapper courseImageMapper;

    @Resource
    CourseMaterialMapper courseMaterialMapper;

    @Resource
    CourseCategoryMapper courseCategoryMapper;

    @Resource
    CourseCatalogueMapper courseCatalogueMapper;

    @Resource
    TeacherMapper teacherMapper;

    @Resource
    StudyCourseMapper studyCourseMapper;

    @Resource
    CourseColumnMapper courseColumnMapper;


    /**
     * 课程列表
     *
     * @param pageParam 分页参数
     * @param params 搜索参数
     * @return PageResult<LsCourseListVo>
     */
    @Override
    public PageResult<CourseListVo> list(PageParam pageParam, Map<String, String> params) {
        Integer page  = pageParam.getPageNo();
        Integer limit = pageParam.getPageSize();
        MPJQueryWrapper<Course> mpjQueryWrapper = new MPJQueryWrapper<Course>()
                .selectAll(Course.class)
                .select("teacher.name as teacherName, category.name as category")
                .innerJoin("?_teacher teacher ON teacher.id=t.teacher_id".replace("?_", GlobalConfig.knowledgePaymentTablePrefixe))
                .innerJoin("?_course_category category ON category.id=t.category_id".replace("?_", GlobalConfig.knowledgePaymentTablePrefixe))
                .orderByDesc(Arrays.asList("t.sort", "t.id"));

        if (StringUtil.isNotEmpty(params.get("categoryId"))) {
            Integer categoryId = Integer.parseInt(params.get("categoryId"));
            List<Integer> categoryIds = this.courseCategoryMapper.getChildrenCategoryId(categoryId);
            categoryIds.add(categoryId);
            mpjQueryWrapper.in("t.category_id", categoryIds);
        }

        courseMapper.setSearch(mpjQueryWrapper, params, new String[]{
                "like:name@t.name:str",
                "like:teacherName@teacher.name:str",
                "=:type@t.type:int",
                "=:feeType@t.fee_type:int",
                "=:status@t.status:int",
        });
        IPage<CourseListVo> iPage = courseMapper.selectJoinPage(new Page<>(page, limit), CourseListVo.class, mpjQueryWrapper);

        for(CourseListVo item : iPage.getRecords()) {
            item.setCover(UrlUtil.toAbsoluteUrl(item.getCover()));
            item.setCreateTime(TimeUtil.timestampToDate(item.getCreateTime()));
            item.setUpdateTime(TimeUtil.timestampToDate(item.getUpdateTime()));
        }

        return PageResult.iPageHandle(iPage.getTotal(), iPage.getCurrent(), iPage.getSize(), iPage.getRecords());
    }

    @Override
    public List<UserCourseListVo> listByUser(Integer userId) {
        MPJQueryWrapper<Course> mpjQueryWrapper = new MPJQueryWrapper<Course>()
                .selectAll(Course.class)
                .select("sc.create_time AS orderCreateTime")
                .innerJoin("?_study_course sc ON sc.course_id = t.id ".replace("?_", GlobalConfig.knowledgePaymentTablePrefixe))
//                .innerJoin("?_order o ON o.id = sc.source_id".replace("?_", GlobalConfig.knowledgePaymentTablePrefixe))
                .eq("sc.user_id", userId)
                .isNull("sc.delete_time")
                .orderByDesc(Arrays.asList("sc.update_time"));

        List<UserCourseListVo> courses = courseMapper.selectJoinList(UserCourseListVo.class, mpjQueryWrapper);

        for(UserCourseListVo item : courses) {
            item.setCover(UrlUtil.toAbsoluteUrl(item.getCover()));
            item.setCreateTime(TimeUtil.timestampToDate(item.getCreateTime()));
//            item.setUpdateTime(TimeUtil.timestampToDate(item.getUpdateTime()));
            item.setPayTime(TimeUtil.timestampToDate(item.getPayTime()));
            item.setCancelTime(TimeUtil.timestampToDate(item.getCancelTime()));
            item.setRefundTime(TimeUtil.timestampToDate(item.getRefundTime()));
            item.setOrderCreateTime(TimeUtil.timestampToDate(item.getOrderCreateTime()));
        }

        return courses;
    }


    @Override
    public List<CourseColumnListVo> listColumns(PageParam pageParam, Map<String, String> params, Integer courseId) {
        MPJQueryWrapper<Course> mpjQueryWrapper = new MPJQueryWrapper<Course>()
                .selectAll(Course.class)
                .select("teacher.name as teacherName, category.name as category, c.id as columnId, c.fee_type as columnFeeType ")
                .innerJoin("?_course_column c ON t.id = c.relation_id".replace("?_", GlobalConfig.knowledgePaymentTablePrefixe))
                .leftJoin("?_teacher teacher ON teacher.id=t.teacher_id".replace("?_", GlobalConfig.knowledgePaymentTablePrefixe))
                .leftJoin("?_course_category category ON category.id=t.category_id".replace("?_", GlobalConfig.knowledgePaymentTablePrefixe))
                .eq("c.course_id", courseId)
                .orderByDesc(Arrays.asList("t.sort", "t.id"));
        courseMapper.setSearch(mpjQueryWrapper, params, new String[]{
                "like:name@t.name:str",
                "=:type@t.type:int",
        });
        List<CourseColumnListVo> result = courseMapper.selectJoinList(CourseColumnListVo.class, mpjQueryWrapper);
        for(CourseColumnListVo item : result) {
            item.setCreateTime(TimeUtil.timestampToDate(item.getCreateTime()));
            item.setUpdateTime(TimeUtil.timestampToDate(item.getUpdateTime()));
        }

        return result;
    }

    /**
     * 课程详情
     *
     * @param id 主键参数
     * @return LsCourse
     */
    @Override
    public CourseDetailVo detail(Integer id) {
        Course model = courseMapper.selectOne(
                new QueryWrapper<Course>()
                    .eq("id", id)
                    .last("limit 1"));
        Assert.notNull(model, "数据不存在");
        CourseDetailVo vo = new CourseDetailVo();
        BeanUtils.copyProperties(model, vo);
        vo.setCoverPath(UrlUtil.toAbsoluteUrl(vo.getCover()));
        vo.setCover(UrlUtil.toAbsoluteUrl(vo.getCover()));
        List<CourseImage> courseImages = courseImageMapper.selectList(new QueryWrapper<CourseImage>().eq("course_id", id));
        List<String> images = new ArrayList<>();
        courseImages.forEach(item -> {
            images.add(UrlUtil.toAbsoluteUrl(item.getUri()));
        });
        vo.setImages(images);
        return vo;
    }

    /**
     * 课程新增
     *
     * @param courseParam 参数
     */
    @Override
    public void add(CourseParam courseParam) {

        if (courseParam.getFeeType().intValue() == 1) {
            Assert.notNull(courseParam.getSellPrice(), "售价不能为空");
            Assert.isTrue(courseParam.getSellPrice().compareTo(BigDecimal.ZERO) == 1, "售价不能小于等于0");
        }
        String courseName = courseParam.getName();
        Course course = courseMapper.selectOne(
                new QueryWrapper<Course>()
                        .eq("name", courseName)
                        .last("limit 1"));
        Assert.isNull(course, "当前课程名称已被占用");
        CourseCategory courseCategory = courseCategoryMapper.selectOne(
                new QueryWrapper<CourseCategory>()
                        .eq("id", courseParam.getCategoryId()));
        Assert.notNull(courseCategory, "分类不存在");
        Teacher teacher = teacherMapper.selectOne(
                new QueryWrapper<Teacher>()
                        .eq("id", courseParam.getTeacherId()));
        Assert.notNull(teacher, "讲师不存在");
        Course model = new Course();
        model.setType(courseParam.getType());
        model.setName(courseName);
        model.setCategoryId(courseParam.getCategoryId());
        model.setTeacherId(courseParam.getTeacherId());
        model.setSynopsis(courseParam.getSynopsis());
        model.setCover(UrlUtil.toRelativeUrl(courseParam.getCover()));
        model.setContent(courseParam.getContent());
        model.setFeeType(courseParam.getFeeType());
        model.setSellPrice(courseParam.getSellPrice());
        model.setLinePrice(courseParam.getLinePrice());
        model.setVirtualStudyNum(courseParam.getVirtualStudyNum());
//        model.setStudyNum(courseParam.getStudyNum());
        model.setStatus(courseParam.getStatus());
        model.setIsChoice(courseParam.getIsChoice());
        model.setSort(courseParam.getSort());
        model.setCreateTime(System.currentTimeMillis() / 1000);
        model.setUpdateTime(System.currentTimeMillis() / 1000);
        courseMapper.insert(model);
        List<String> images = courseParam.getImages();
        images.forEach(item -> {
            CourseImage courseImage = new CourseImage();
            courseImage.setCourseId(model.getId());
            courseImage.setUri(UrlUtil.toRelativeUrl(item));
            courseImageMapper.insert(courseImage);
        });
    }

    /**
     * 课程编辑
     *
     * @param courseParam 参数
     */
    @Override
    public void edit(CourseParam courseParam) {
        String courseName = courseParam.getName();
        Course model = courseMapper.selectOne(
                new QueryWrapper<Course>()
                    .eq("id",  courseParam.getId())
                    .last("limit 1"));
        Assert.notNull(model, "数据不存在!");

        Course course = courseMapper.selectOne(
                new QueryWrapper<Course>()
                        .eq("name", courseName)
                        .last("limit 1"));

        if (course != null) {
            Assert.isTrue(course.getId().intValue() == courseParam.getId().intValue(), "当前课程名称已被占用");
        }

        CourseCategory courseCategory = courseCategoryMapper.selectOne(
                new QueryWrapper<CourseCategory>()
                        .eq("id", courseParam.getCategoryId()));
        Assert.notNull(courseCategory, "分类不存在");

        Teacher teacher = teacherMapper.selectOne(
                new QueryWrapper<Teacher>()
                        .eq("id", courseParam.getTeacherId()));

        Assert.notNull(teacher, "讲师不存在");
        model.setId(courseParam.getId());
        model.setType(courseParam.getType());
        model.setName(courseParam.getName());
        model.setCategoryId(courseParam.getCategoryId());
        model.setTeacherId(courseParam.getTeacherId());
        model.setSynopsis(courseParam.getSynopsis());
        model.setCover(UrlUtil.toRelativeUrl(courseParam.getCover()));
        model.setContent(courseParam.getContent());
        model.setFeeType(courseParam.getFeeType());
        model.setSellPrice(courseParam.getSellPrice());
        model.setLinePrice(courseParam.getLinePrice());
        model.setVirtualStudyNum(courseParam.getVirtualStudyNum());
        model.setStudyNum(courseParam.getStudyNum());
        model.setStatus(courseParam.getStatus());
        model.setIsChoice(courseParam.getIsChoice());
        model.setSort(courseParam.getSort());
        model.setUpdateTime(System.currentTimeMillis() / 1000);
        courseMapper.updateById(model);
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.eq("course_id",courseParam.getId());
        this.courseImageMapper.delete(wrapper);
        List<String> images = courseParam.getImages();
        images.forEach(item -> {
            CourseImage courseImage = new CourseImage();
            courseImage.setCourseId(model.getId());
            courseImage.setUri(UrlUtil.toRelativeUrl(item));
            courseImageMapper.insert(courseImage);
        });

    }

    /**
     * 课程删除
     *
     * @param id 主键ID
     */
    @Override
    public void del(String id) {
        String[] ids = id.split(",");
        for(int i = 0; i < ids.length; i++) {
            Course model = courseMapper.selectOne(
                    new QueryWrapper<Course>()
                            .eq("id", ids[i])
                            .last("limit 1"));
            Assert.notNull(model, "数据不存在!");
            Integer count = this.studyCourseMapper.selectCount(new QueryWrapper<StudyCourse>()
                    .eq("course_id", ids[i]));
            Assert.isTrue(count.intValue() == 0, "该课程存在用户购买");

            this.courseMapper.delete(new QueryWrapper<Course>().eq("id", ids[i]));

            this.courseImageMapper.delete(new QueryWrapper<CourseImage>().eq("course_id", ids[i]));

            this.courseCatalogueMapper.delete(new QueryWrapper<CourseCatalogue>().eq("course_id", ids[i]));

            this.courseMaterialMapper.delete(new QueryWrapper<CourseMaterial>().eq("course_id", ids[i]));
        }

    }

    @Override
    public void changeStatus(String id, String status) {
        String[] ids = id.split(",");
        for(int i = 0; i < ids.length; i++) {
            Course course = courseMapper.selectOne(
                    new QueryWrapper<Course>()
                            .eq("id", ids[i])
                            .last("limit 1"));
            Assert.notNull(course, "课程不存在!");

            if (StringUtil.isNotEmpty(status)) {
                course.setStatus(Integer.parseInt(status));
            } else {
                course.setStatus(course.getStatus() == 1 ? 0 : 1);
            }

            course.setUpdateTime(TimeUtil.timestamp());
            courseMapper.updateById(course);
        }
    }

    /**
     * 专栏课程关联新增
     *
     * @author panweiliang
     * @param courseColumnParam 参数
     */
    @Override
    public void addColumn(CourseColumnParam courseColumnParam) {

        Course courseModel = courseMapper.selectOne(
                new QueryWrapper<Course>()
                        .eq("id", courseColumnParam.getCourseId())
                        .last("limit 1"));
        Assert.notNull(courseModel, "专栏不存在!");


        Course relationModel = courseMapper.selectOne(
                new QueryWrapper<Course>()
                        .eq("id", courseColumnParam.getRelationId())
                        .last("limit 1"));
        Assert.notNull(relationModel, "课程不存在!");


        CourseColumn courseColumn = courseColumnMapper.selectOne(
                new QueryWrapper<CourseColumn>()
                        .eq("course_id", courseColumnParam.getCourseId())
                        .eq("relation_id", courseColumnParam.getRelationId())
                        .last("limit 1"));

        Assert.isNull(courseColumn, "专栏已经引用了课程，不能重复引用!");

        CourseColumn model = new CourseColumn();
        model.setCourseId(courseColumnParam.getCourseId());
        model.setRelationId(courseColumnParam.getRelationId());
        model.setFeeType(courseColumnParam.getFeeType());
        model.setSort(courseColumnParam.getSort());
        model.setCreateTime(System.currentTimeMillis() / 1000);
        model.setUpdateTime(System.currentTimeMillis() / 1000);
        courseColumnMapper.insert(model);
    }

    /**
     * 专栏课程关联删除
     *
     * @author panweiliang
     * @param id 主键ID
     */
    @Override
    public void delColumn(Integer id) {
        CourseColumn model = courseColumnMapper.selectOne(
                new QueryWrapper<CourseColumn>()
                        .eq("id", id)
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在!");

        courseColumnMapper.delete(new QueryWrapper<CourseColumn>().eq("id", id));
    }

    /**
     * 回收课程
     * @author panweiliang
     * @param userId 用户id
     * @param courseId 课程id
     */
    public void delCourseStudy(Integer userId, Integer courseId) {

        StudyCourse model = studyCourseMapper.selectOne(
                new QueryWrapper<StudyCourse>()
                        .eq("user_id", userId)
                        .eq("course_id", courseId)
                        .isNull("delete_time")
                        .last("limit 1"));

        Assert.notNull(model, "数据不存在!");

        model.setDeleteTime(TimeUtil.timestamp());

        Course course = this.courseMapper.selectById(courseId);
        if (course != null) {
            Integer studyNum = course.getStudyNum();
            studyNum = studyNum != null ? studyNum : 0;
            studyNum = studyNum - 1;
            studyNum = studyNum < 0 ? 0 : studyNum;
            course.setStudyNum(studyNum);
            this.courseMapper.updateById(course);
        }

        this.studyCourseMapper.updateById(model);

    }


    @Override
    public CourseColumn changeColumnFeeType(Integer id) {
        CourseColumn courseColumn = courseColumnMapper.selectOne(
                new QueryWrapper<CourseColumn>()
                        .eq("id", id)
                        .last("limit 1"));
        Assert.notNull(courseColumn, "专栏目录不存在!");
        courseColumn.setFeeType(courseColumn.getFeeType() == 1 ? 0 : 1);
        courseColumn.setUpdateTime(TimeUtil.timestamp());
        courseColumnMapper.updateById(courseColumn);
        return courseColumn;
    }

    @Override
    public Long countByCategory(Integer categoryId) {
        return this.courseMapper.countByCategory(categoryId);
    }
}
